﻿using BootstrapBlazor.Components;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Options;
using LaserMark.Extensions;
using LaserMark.Components.Services;
using LaserMark.Control.Service;
using LaserMark.View.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;

namespace LaserMark.Components.Components
{
    public partial class ZeroControl : IAsyncDisposable
    {
        [Inject]
        [NotNull]
        private IControl? Control { get; set; }

        [Inject]
        [NotNull]
        private IGlobalStatus? GlobalStatus { get; set; }

        [Inject]
        [NotNull]
        private IOptions<MarkOption>? Options { get; set; }

        [NotNull]
        private MarkOption? MarkOptions { get; set; }

        private bool IsXZero { get; set; }

        private bool IsYZero { get; set; }

        private bool IsZZero { get; set; }

        [NotNull]
        private Color Axis2Limit { get; set; } = Color.Success;

        [NotNull]
        private Color Axis3Limit { get; set; } = Color.Success;

        [NotNull]
        private Color Axis4Limit { get; set; } = Color.Success;

        [NotNull]
        private Color Axis4Limit2 { get; set; } = Color.Success;

        /// <summary>
        ///
        /// </summary>
        public string? X { get; set; }

        /// <summary>
        ///
        /// </summary>
        public string? Y { get; set; }

        /// <summary>
        ///
        /// </summary>
        public string? Z { get; set; }

        protected override void OnInitialized()
        {
            base.OnInitialized();
            MarkOptions = Options.Value;
            System.Timers.Timer timer = new System.Timers.Timer(50);
            timer.Elapsed += TimerHandler;
            timer.Start();
        }

        private async void TimerHandler(object? sender, ElapsedEventArgs e)
        {
            try
            {
                if (GlobalStatus.IsRunning)
                {
                    await Control.GetAxisStatus(0, (short)MarkOptions.AxisCode.X, out int value2, 1, out _);
                    await Control.GetAxisStatus(0, (short)MarkOptions.AxisCode.Y, out int value3, 1, out _);
                    await Control.GetAxisStatus(0, (short)MarkOptions.AxisCode.Z, out int value4, 1, out _);

                    mc.GT_GetEncPos(0, (short)MarkOptions.AxisCode.X, out double enc1, 1, out _);
                    X = (Convert.ToDouble(enc1) * MarkOptions.XPluse.Value).ToString("0.00");
                    mc.GT_GetEncPos(0, (short)MarkOptions.AxisCode.Y, out double enc2, 1, out _);
                    Y = (Convert.ToDouble(enc2) * MarkOptions.YPluse.Value).ToString("0.00");
                    mc.GT_GetEncPos(0, (short)MarkOptions.AxisCode.Z, out double enc3, 1, out _);
                    Z = (Convert.ToDouble(enc3) * MarkOptions.ZPluse.Value).ToString("0.00");

                    //2#正负限位
                    if ((value2 & 0x20) != 0)
                    {
                        Axis2Limit = Color.Danger;
                    }
                    else
                    {
                        Axis2Limit = Color.Success;
                    }

                    //3#正负限位
                    if ((value3 & 0x20) != 0)
                    {
                        Axis3Limit = Color.Danger;
                    }
                    else
                    {
                        Axis3Limit = Color.Success;
                    }

                    //4#正限位
                    if ((value4 & 0x20) != 0)
                    {
                        Axis4Limit = Color.Danger;
                    }
                    else
                    {
                        Axis4Limit = Color.Success;
                    }

                    //4#负限位
                    if ((value4 & 0x40) != 0)
                    {
                        Axis4Limit2 = Color.Danger;
                    }
                    else
                    {
                        Axis4Limit2 = Color.Success;
                    }

                    await InvokeAsync(StateHasChanged);
                }
            }
            catch (Exception)
            {
            }
        }

        private async Task OnXZero()
        {
            IsXZero = true;
            await Control.GetAxisStatus(0, (short)MarkOptions.AxisCode.X, out int status, 1, out _);
            if ((status & 0x400) == 0)
            {
                _ = Task.Run(async () =>
                {
                    var pluse = MarkOptions.ZeroOffSet.X / MarkOptions.XPluse.Value;
                    var ret = GoHomeExtension.Go((short)MarkOptions.AxisCode.X, (int)pluse, -((int)MarkOptions.ZeroVel.X), ((int)MarkOptions.ZeroVel.X), MarkOptions.ZeroAcc.X / 10000, MarkOptions.ZeroDec.X / 10000);
                    if (ret)
                    {
                        IsXZero = false;

                        await InvokeAsync(StateHasChanged);
                    }
                });
            }
        }

        private async Task OnYZero()
        {
            IsYZero = true;
            await Control.GetAxisStatus(0, (short)MarkOptions.AxisCode.Y, out int status, 1, out _);
            if ((status & 0x400) == 0)
            {
                _ = Task.Run(async () =>
                {
                    var pluse = MarkOptions.ZeroOffSet.Y / MarkOptions.YPluse.Value;
                    var ret = GoHomeExtension.Go((short)MarkOptions.AxisCode.Y, (int)pluse, -((int)MarkOptions.ZeroVel.Y), ((int)MarkOptions.ZeroVel.Y), MarkOptions.ZeroAcc.Y / 10000, MarkOptions.ZeroDec.Y / 10000);
                    if (ret)
                    {
                        IsYZero = false;
                        GlobalStatus.IsYZeroBack = true;
                        await InvokeAsync(StateHasChanged);
                    }
                });
            }
        }

        private async Task OnZZero()
        {
            IsZZero = true;
            await Control.GetAxisStatus(0, (short)MarkOptions.AxisCode.Z, out int status, 1, out _);
            if ((status & 0x400) == 0)
            {
                _ = Task.Run(async () =>
                {
                    var pluse = MarkOptions.ZeroOffSet.Z / MarkOptions.ZPluse.Value;
                    var ret = GoHomeExtension.Go((short)MarkOptions.AxisCode.Z, (int)pluse, -((int)MarkOptions.ZeroVel.Z), ((int)MarkOptions.ZeroVel.Z), MarkOptions.ZeroAcc.Z / 10000, MarkOptions.ZeroDec.Z / 10000);
                    if (ret)
                    {
                        IsZZero = false;
                        GlobalStatus.IsXZeroBack = true;
                        await InvokeAsync(StateHasChanged);
                    }
                });
            }
        }

        private async Task OnStop()
        {
            await Control.Stop(0, 1 << ((int)MarkOptions.AxisCode.X - 1), 1);
            await Control.Stop(0, 1 << ((int)MarkOptions.AxisCode.Y - 1), 1);
            await Control.Stop(0, 1 << ((int)MarkOptions.AxisCode.Z - 1), 1);
        }

        public async ValueTask DisposeAsync()
        {
            await Control.Stop(0, 1 << ((int)MarkOptions.AxisCode.X - 1), 1);
            await Control.Stop(0, 1 << ((int)MarkOptions.AxisCode.Y - 1), 1);
            await Control.Stop(0, 1 << ((int)MarkOptions.AxisCode.Z - 1), 1);

            GC.SuppressFinalize(this);
        }
    }
}
